#include <event2/event.h>
#include <stdlib.h>
/* When we allocate an event_pair in memory, we’ll actually allocate
 * more space at the end of the structure. We define some macros
 * to make accessing those events less error-prone.
 */
struct event_pair {
    evutil_socket_t fd;
};
/* Macro: yield the struct event ’offset’ bytes from the start of ’p’ */
#define EVENT_AT_OFFSET(p, offset) \
        ((struct event * ) ( ((char * )(p)) + (offset) ))
/* Macro: yield the read event of an event_pair */
#define READEV_PTR(pair) \
        EVENT_AT_OFFSET((pair), sizeof(struct event_pair))
/* Macro: yield the write event of an event_pair */
#define WRITEEV_PTR(pair) \
        EVENT_AT_OFFSET((pair), \
sizeof(struct event_pair)+event_get_struct_event_size())
/* Macro: yield the actual size to allocate for an event_pair */
#define EVENT_PAIR_SIZE() \
        (sizeof(struct event_pair)+2 * event_get_struct_event_size())
void cb_func(evutil_socket_t fd, short what, void* arg);
struct event_pair* event_pair_new(struct event_base * base, evutil_socket_t fd)
{
    struct event_pair* p = malloc(EVENT_PAIR_SIZE());
    if (!p) return NULL;
    p->fd = fd;
    event_assign(READEV_PTR(p), base, fd, EV_READ|EV_PERSIST, cb_func, p);
    event_assign(WRITEEV_PTR(p), base, fd, EV_WRITE|EV_PERSIST, cb_func, p);
    return p;
}
int main()
{
    struct event_base* base = event_base_new();
    struct event_pair* event=event_pair_new(base,fileno(stderr));
    struct timeval five_ses = {5,0};
    event_add(READEV_PTR(event),&five_ses);
    event_base_dispatch(base);

    return 0;
}
void cb_func(evutil_socket_t fd, short what, void* arg)
{
    const char* data = arg;
    printf("Got an event on socket %d:%s%s%s%s [%s]\n",
        (int) fd,
        (what&EV_TIMEOUT) ? " timeout" : "",
        (what&EV_READ) ? " read" : "",
        (what&EV_WRITE) ? " write" : "",
        (what&EV_SIGNAL) ? " signal" : "",
        data);
}